# -*- coding: utf-8 -*-
"""
QAD 服务器配置模型
用于管理远程服务器连接配置和路径设置
"""

from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
from datetime import datetime

_logger = logging.getLogger(__name__)


class QADServerConfig(models.Model):
    """QAD 服务器连接配置"""
    _name = 'qad.server.config'
    _description = 'QAD Server Configuration'
    _rec_name = 'server_code'
    _order = 'server_code'

    # 基本信息
    server_code = fields.Char(
        string='服务器代码',
        required=True,
        index=True,
        help='唯一标识此服务器配置的代码，API 调用时使用此代码识别目标服务器'
    )
    name = fields.Char(
        string='配置名称',
        required=True,
        help='服务器配置的描述性名称'
    )
    active = fields.Boolean(
        string='启用',
        default=True,
        help='是否启用此服务器配置'
    )
    
    # 连接类型
    connection_type = fields.Selection([
        ('local', '本地执行'),
        ('ssh', 'SSH 远程连接'),
    ], string='连接类型', required=True, default='ssh',
       help='选择脚本执行方式：本地或通过 SSH 远程执行')
    
    # SSH 连接信息
    host = fields.Char(
        string='目标 IP 地址',
        help='远程服务器的 IP 地址或主机名'
    )
    port = fields.Integer(
        string='SSH 端口',
        default=22,
        help='SSH 连接端口，默认 22'
    )
    
    # SSH 认证方式
    auth_type = fields.Selection([
        ('password', '密码认证'),
        ('key', '密钥认证'),
    ], string='认证方式', default='password',
       help='SSH 认证方式：密码或公钥')
    
    ssh_username = fields.Char(
        string='Linux 用户名',
        help='SSH 登录的 Linux 用户名'
    )
    ssh_password = fields.Char(
        string='Linux 密码',
        help='SSH 登录密码（如果使用密码认证）'
    )
    ssh_private_key = fields.Text(
        string='SSH 私钥',
        help='SSH 私钥内容（如果使用密钥认证）'
    )
    ssh_key_passphrase = fields.Char(
        string='密钥密码',
        help='SSH 私钥的密码（如果有）'
    )
    
    # 应用系统登录信息
    app_username = fields.Char(
        string='应用系统用户名',
        help='目标应用系统的登录用户名'
    )
    app_password = fields.Char(
        string='应用系统密码',
        help='目标应用系统的登录密码'
    )
    login_script = fields.Char(
        string='登录脚本名',
        help='用于登录应用系统的脚本文件名'
    )
    login_program = fields.Char(
        string='登录程序名',
        help='登录脚本需要调用的程序名称'
    )
    login_options = fields.Char(
        string='登录选项',
        help='登录时需要传递的额外选项或参数'
    )
    
    # 路径配置
    work_path = fields.Char(
        string='工作路径',
        required=True,
        default='/tmp/qad_work',
        help='脚本执行的工作目录'
    )
    input_path = fields.Char(
        string='输入路径',
        help='输入文件存放目录'
    )
    output_path = fields.Char(
        string='输出路径',
        required=True,
        help='JSON 输出文件存放目录'
    )
    archive_path = fields.Char(
        string='存档路径',
        help='已处理文件的存档目录'
    )
    success_path = fields.Char(
        string='处理成功路径',
        help='处理成功的文件存放目录'
    )
    error_path = fields.Char(
        string='处理失败路径',
        help='处理失败的文件存放目录'
    )
    
    # 超时和重试配置
    connection_timeout = fields.Integer(
        string='连接超时（秒）',
        default=30,
        help='SSH 连接超时时间'
    )
    execution_timeout = fields.Integer(
        string='执行超时（秒）',
        default=300,
        help='脚本执行超时时间'
    )
    
    # 统计信息
    endpoint_count = fields.Integer(
        string='接口数量',
        compute='_compute_endpoint_count',
        store=True,
        help='使用此服务器配置的接口数量'
    )
    last_connection_time = fields.Datetime(
        string='最后连接时间',
        readonly=True,
        help='最后一次成功连接的时间'
    )
    last_connection_status = fields.Selection([
        ('success', '成功'),
        ('failed', '失败'),
    ], string='最后连接状态', readonly=True)
    last_error_message = fields.Text(
        string='最后错误信息',
        readonly=True,
        help='最后一次连接或执行的错误信息'
    )
    
    # 备注
    notes = fields.Text(
        string='备注',
        help='关于此服务器配置的额外说明'
    )
    
    # SQL 约束
    _sql_constraints = [
        ('server_code_unique', 'UNIQUE(server_code)',
         '服务器代码必须唯一！'),
    ]
    
    @api.depends('server_code')
    def _compute_endpoint_count(self):
        """计算使用此服务器配置的接口数量"""
        for record in self:
            record.endpoint_count = self.env['qad.api.endpoint'].search_count([
                ('server_config_id', '=', record.id)
            ])
    
    @api.constrains('port')
    def _check_port(self):
        """检查端口号是否有效"""
        for record in self:
            if record.connection_type == 'ssh' and record.port:
                if record.port < 1 or record.port > 65535:
                    raise ValidationError(_('端口号必须在 1-65535 之间！'))
    
    @api.constrains('connection_timeout', 'execution_timeout')
    def _check_timeout(self):
        """检查超时时间是否有效"""
        for record in self:
            if record.connection_timeout < 1:
                raise ValidationError(_('连接超时时间必须大于 0！'))
            if record.execution_timeout < 1:
                raise ValidationError(_('执行超时时间必须大于 0！'))
    
    @api.onchange('connection_type')
    def _onchange_connection_type(self):
        """当连接类型改变时，清空不需要的字段"""
        if self.connection_type == 'local':
            self.host = False
            self.port = 22
            self.ssh_username = False
            self.ssh_password = False
            self.ssh_private_key = False
    
    def action_test_connection(self):
        """测试服务器连接"""
        self.ensure_one()
        
        try:
            if self.connection_type == 'local':
                # 测试本地连接（检查路径是否存在）
                import os
                if not os.path.exists(self.work_path):
                    raise ValidationError(_('工作路径不存在：%s') % self.work_path)
                
                message = _('✅ 本地连接测试成功！\n工作路径可访问：%s') % self.work_path
                
            elif self.connection_type == 'ssh':
                # 测试 SSH 连接
                if not self.host or not self.ssh_username:
                    raise ValidationError(_('请填写 SSH 连接必需的字段（主机、用户名）！'))
                
                # 这里简化处理，实际应该尝试 SSH 连接
                # import paramiko 会在 controller 中实现
                message = _('✅ SSH 连接配置有效！\n主机：%s\n端口：%s\n用户：%s') % (
                    self.host, self.port, self.ssh_username
                )
            
            # 更新连接状态
            self.write({
                'last_connection_time': fields.Datetime.now(),
                'last_connection_status': 'success',
                'last_error_message': False,
            })
            
            return {
                'type': 'ir.actions.client',
                'tag': 'display_notification',
                'params': {
                    'title': _('连接测试'),
                    'message': message,
                    'type': 'success',
                    'sticky': False,
                }
            }
            
        except Exception as e:
            # 更新连接状态
            self.write({
                'last_connection_time': fields.Datetime.now(),
                'last_connection_status': 'failed',
                'last_error_message': str(e),
            })
            
            return {
                'type': 'ir.actions.client',
                'tag': 'display_notification',
                'params': {
                    'title': _('连接测试失败'),
                    'message': str(e),
                    'type': 'danger',
                    'sticky': True,
                }
            }
    
    def action_view_endpoints(self):
        """查看使用此服务器配置的接口"""
        self.ensure_one()
        
        return {
            'type': 'ir.actions.act_window',
            'name': _('相关接口'),
            'res_model': 'qad.api.endpoint',
            'view_mode': 'tree,form',
            'domain': [('server_config_id', '=', self.id)],
            'context': {'default_server_config_id': self.id},
        }

    @api.model
    def _generate_unique_server_code(self, base_code):
        """生成唯一的服务器代码"""
        if not base_code:
            base_code = "SERVER"
        
        # 移除末尾的数字和 _COPY_ 部分（如果有的话）
        base_code = base_code.rstrip('0123456789')
        if base_code.endswith('_COPY'):
            base_code = base_code[:-5]  # 移除 _COPY
        
        counter = 1
        new_code = f"{base_code}_COPY_{counter}"
        
        # 确保代码唯一
        while self.search([('server_code', '=', new_code)], limit=1):
            counter += 1
            new_code = f"{base_code}_COPY_{counter}"
        
        return new_code

    def copy(self, default=None):
        """复制记录时生成临时的唯一值"""
        if default is None:
            default = {}
        
        # 生成临时的服务器代码
        original_code = self.server_code or "SERVER"
        temp_code = self._generate_unique_server_code(original_code)
        
        default.update({
            'server_code': temp_code,
            'name': f"{self.name} (副本)" if self.name else "服务器配置副本",
            'active': False,  # 默认禁用，避免意外使用
        })
        
        return super(QADServerConfig, self).copy(default)

